package com.gxa.learning.pc.service.impl;

import com.gxa.learning.core.common.ExceptionCode;
import com.gxa.learning.core.exception.BusinessException;
import com.gxa.learning.core.pojo.Project;
import com.gxa.learning.core.pojo.ProjectDetails;
import com.gxa.learning.core.pojo.Score;
import com.gxa.learning.core.service.impl.BaseServiceImpl;
import com.gxa.learning.pc.mapper.ProjectDetailsMapper;
import com.gxa.learning.pc.mapper.ProjectMapper;
import com.gxa.learning.pc.mapper.ProjectSignMapper;
import com.gxa.learning.pc.mapper.ScoreMapper;
import com.gxa.learning.pc.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
public class TestServiceImpl extends BaseServiceImpl<Score> implements TestService {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private ScoreMapper scoreMapper = null;

    @Autowired
    private ProjectSignMapper projectSignMapper = null;

    @Autowired
    private ProjectDetailsMapper projectDetailsMapper = null;

    @Autowired
    private ProjectMapper projectMapper = null;

    public static final String TESTKEY = "wodekaoshi";


    @Override
    public void sendTest(Long qid, Long pid, Integer passScore, Integer testTime, Integer endDay) throws BusinessException {

        if (qid == null || pid == null || passScore == null || testTime == null || endDay == null) {
            throw new BusinessException(ExceptionCode.ARGUMENTS_ERROR);
        }
        //判断项目的状态是否是可用的
        ProjectDetails projectDetails = projectDetailsMapper.selectByPrimaryKey(pid);
        Project project = projectMapper.selectByPrimaryKey(pid);
        if (projectDetails == null || project == null) {
            throw new BusinessException(ExceptionCode.WRONG_PROJECT);
        }
        String projectName = project.getProjectName();
        long startTime = projectDetails.getProjectStartTime().getTime();
        long endTime = projectDetails.getProjectEndTime().getTime();
        long now = new Date().getTime();
        if (now < startTime || now > endTime) {
            throw new BusinessException(ExceptionCode.TIME_OUT_OF_PROJECT);
        }
        //用来表示不同考试的序列号
        String scoreTest = UUID.randomUUID().toString();
        scoreTest = scoreTest.replaceAll("-", "");
        //把所有符合条件的学员存到数据库，把分数
        //获取本项目的所有学员
        List<Long> nums = projectSignMapper.getNotSignNum(pid);
        ArrayList<Score> scores = new ArrayList<>();
        //添加到数据库
        for (Long num : nums) {
            Score score = new Score();
            score.setProjectCourseId(pid);
            score.setUserId(num);
            score.setStatus(0);
            score.setTime(new Date());
            score.setScoreKey(scoreTest);
            scores.add(score);

        }
        if (scores.size() <= 0) {
            throw new BusinessException(ExceptionCode.HAS_NO_STUDENTS);
        }
        Integer integer = scoreMapper.addScoresBatch(scores);
        if (integer < 1) {
            throw new BusinessException(ExceptionCode.FAILED_OPTION);
        }

        //设置这次考试时间的过期键
        redisTemplate.opsForValue().setIfAbsent(TESTKEY + scoreTest, scoreTest, 14, TimeUnit.DAYS);

        //本次考试信息存到redis
        HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
        hashOps.put(scoreTest, "qid", qid);
        hashOps.put(scoreTest, "projectName", projectName);
        hashOps.put(scoreTest, "pid", pid);
        hashOps.put(scoreTest, "passScore", passScore);
        hashOps.put(scoreTest, "testTime", testTime);
        hashOps.put(scoreTest, "endDay", endDay);
    }

    @Override
    public List<Map<String, Object>> getScoreList(Long pid, String name, String company, String department, Integer page, Integer size) throws BusinessException {
        if (pid == null || pid <= 0) {
            throw new BusinessException(ExceptionCode.ARGUMENTS_ERROR);
        }

        if (page == null) {
            page = 1;
        }
        if (size == null) {
            size = 5;
        }
        Integer offset = (page - 1) * size;
        List<Map<String, Object>> scoreList = scoreMapper.getScoreList(pid, name, company, department, offset, size);
        if (scoreList == null || scoreList.size() == 0) {
            throw new BusinessException(ExceptionCode.WRONG_DATA);
        }
        HashOperations<String, Object, Object> forHash = redisTemplate.opsForHash();
        for (Map<String, Object> map : scoreList) {
            Integer status = (Integer) map.get("status");
            if (status != null && status == 0) {
                String key = (String) map.get("key");
                Date time = (Date) map.get("time");
                Integer endDay = (Integer) forHash.get(key, "endDay");
                if (endDay == null) {
                    throw new BusinessException(ExceptionCode.WRONG_PROJECT);
                }
                if ((System.currentTimeMillis() - time.getTime()) > (endDay * 60 * 60 * 24 * 1000)) {
                    scoreMapper.updateStatus((Long) map.get("id"), 2);
                    map.put("status", 2);
                }
            }
        }
        return scoreList;
    }

    @Override
    public List<Map<String, Object>> getAllScoreList(Long pid, String name, String company, String department) throws BusinessException {
        if (pid == null || pid <= 0) {
            throw new BusinessException(ExceptionCode.ARGUMENTS_ERROR);
        }
        List<Map<String, Object>> scoreList = scoreMapper.getScoreList(pid, name, company, department, null, null);
        if (scoreList == null || scoreList.size() == 0) {
            throw new BusinessException(ExceptionCode.WRONG_DATA);
        }
        return scoreList;
    }
}
